"""
Catalog 模块：负责数据库元数据（表、列结构）的管理。

核心设计与优化说明：
- 采用面向对象设计，ColumnSchema/TableSchema/Catalog 各司其职，便于扩展和维护。
- Catalog 作为集中式元数据管理器，支持高效表查找、创建、删除等操作。
- 明确类型注解，提升代码可读性和静态检查能力。
- 错误处理统一，便于调试和调用方异常捕获。
- 字符串方法便于调试和日志输出。
- 预留扩展点（如表/列统计信息、索引元数据等）。
- 支持 VARCHAR(n) 类型，便于与 parser/lexer 兼容。
"""

from typing import List, Dict, Optional, Any
from .lexer import TokenType

class ColumnSchema:
    """
    列模式对象，描述单个列的名称与类型。
    可扩展支持默认值、是否可空、索引等属性。
    """
    def __init__(self, name: str, type: TokenType, length: Optional[int] = None):
        self.name = name
        self.type = type
        self.length = length  # 支持 VARCHAR(n) 的长度

    def __str__(self):
        if self.type == TokenType.VARCHAR and self.length is not None:
            return f"{self.name} {self.type.value}({self.length})"
        return f"{self.name} {self.type.value}"

    def __repr__(self):
        return self.__str__()

class TableSchema:
    """
    表模式对象，描述表名及其所有列的结构。
    可扩展支持主键、唯一约束、表级统计信息等。
    """
    def __init__(self, name: str, columns: List[ColumnSchema]):
        self.name = name
        self.columns = columns

    def __str__(self):
        columns_str = ", ".join([str(col) for col in self.columns])
        return f"Table {self.name} ({columns_str})"

    def __repr__(self):
        return self.__str__()

class Catalog:
    """
    数据库目录（Catalog），负责管理所有表的元数据。
    设计决策：
      - 采用字典结构实现高效表查找。
      - 统一异常处理，便于调用方捕获和日志记录。
      - 便于后续扩展如表统计、索引、权限等。
    """
    def __init__(self):
        self.tables: Dict[str, TableSchema] = {}

    def create_table(self, table_name: str, columns: List[ColumnSchema]) -> None:
        """
        创建新表，若表已存在则抛出异常。
        :param table_name: 表名
        :param columns: 列模式列表
        """
        if table_name in self.tables:
            raise ValueError(f"Table '{table_name}' already exists")
        self.tables[table_name] = TableSchema(table_name, columns)
    
    def get_table(self, table_name: str) -> TableSchema:
        """
        获取指定表的元数据，不存在则抛出异常。
        :param table_name: 表名
        :return: TableSchema
        """
        if table_name not in self.tables:
            raise ValueError(f"Table '{table_name}' does not exist")
        return self.tables[table_name]

    def drop_table(self, table_name: str) -> None:
        """
        删除指定表，若表不存在则抛出异常。
        :param table_name: 表名
        """
        if table_name not in self.tables:
            raise ValueError(f"Table '{table_name}' does not exist")
        del self.tables[table_name]

    def __str__(self):
        return "\n".join([str(table) for table in self.tables.values()])

    def __repr__(self):
        return self.__str__()

    # 新增：辅助方法，便于 parser/plan 层根据 ASTNode 生成列模式
    @staticmethod
    def from_ast_columns(ast_columns: List[Any]) -> List[ColumnSchema]:
        """
        根据 ASTNode 列定义生成 ColumnSchema 列表。
        支持 INT、VARCHAR(n) 等类型。
        """
        columns = []
        for col in ast_columns:
            name = col.value["name"]
            col_type = col.value["type"]
            length = col.value.get("length")
            columns.append(ColumnSchema(name, col_type, length))
        return columns
